Skip to content

fix oob read on malformed length field in dba flatfile handler#22266

Open
alhudz wants to merge 2 commits into
php:masterfrom
alhudz:dba-flatfile-length-overflow
Open

fix oob read on malformed length field in dba flatfile handler#22266
alhudz wants to merge 2 commits into
php:masterfrom
alhudz:dba-flatfile-length-overflow

Conversation

@alhudz

@alhudz alhudz commented Jun 10, 2026

Copy link
Copy Markdown

A flatfile opened read-only parses an attacker-controlled record length, and a negative value overruns the read buffer.

  1. num is a size_t but is assigned from atoi(buf), so a length line of -1 becomes SIZE_MAX.
  2. the grow step then does buf_size = num + FLATFILE_BLOCK_SIZE, which wraps to a tiny value and erealloc shrinks buf.
  3. php_stream_read(dba->fp, buf, num) then reads the rest of the file (num is still SIZE_MAX) into the small buffer.

repro: file_put_contents('x', "-1\n" . str_repeat('A', 200000)); $db = dba_open('x', 'r', 'flatfile'); dba_firstkey($db);
expected: bool(false)
actual: zend_mm_heap corrupted (SIGABRT)

Reachable from dba_firstkey/dba_nextkey/dba_fetch/dba_exists/dba_delete. The same idiom is repeated in flatfile_delete, flatfile_findkey, flatfile_firstkey and flatfile_nextkey, so the guard goes in each. Added a regression test.

Comment thread ext/dba/libflatfile/flatfile.c Outdated
Comment on lines 189 to 195
if (num >= buf_size) {
if (num > SIZE_MAX - FLATFILE_BLOCK_SIZE) {
break;
}
buf_size = num + FLATFILE_BLOCK_SIZE;
buf = erealloc(buf, buf_size);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering how often this is repeated, maybe a macro would make sense ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Folded the parse-and-grow into a FLATFILE_GROW_BUF() macro that yields true when the length would overflow, so the break stays visible at each call site and the eight copies collapse to one. dba_flatfile.phpt, the creation matrix and the new regression test still pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants